//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

using System;
using System.Collections.Generic;
using System.Text;
using System.Xml.Serialization;

namespace Microsoft.Research.DataLayer
{
    public abstract partial class Connection
    {
        /// <summary>
        /// Mark each storage with information about its relation
        /// </summary>
        public enum StorageFlags
        {
            /// <summary>
            /// Simple object.
            /// </summary>
            SimpleObject,

            /// <summary>
            /// Relation object. It means we have custom data + keys.
            /// </summary>
            RelationObject,
        }

        /// <summary>
        /// Represents the types the system can handle.
        /// </summary>
        /// <remarks>They are an enum instead of some runtime value (e.g. string) to
        /// avoid bugs in the code. By having them declared in the system we can use
        /// the compiler to track them, avoid typos, etc.</remarks>
        [Serializable]
        public class Storage
        {
            /// <summary>
            /// No information about the object.
            /// </summary>
            public static Storage None = new Storage("None");

            /// <summary>
            /// Name of the storage object
            /// </summary>
            protected string name;

            /// <summary>
            /// Flags if this is a self relationship
            /// </summary>
            protected bool selfRelation = false;

            /// <summary>
            /// Flags for the storage object
            /// </summary>
            protected StorageFlags flags = StorageFlags.SimpleObject;

            /// <summary>
            /// Initializes a new instance of the <see cref="Storage"/> class.
            /// </summary>
            public Storage()
            {

            }

            /// <summary>
            /// Constructs a new storage type
            /// </summary>
            /// <param name="name"></param>
            protected Storage(string name)
            {
                this.name = name;
            }

            /// <summary>
            /// Constructs a new storage type
            /// </summary>
            /// <param name="name"></param>
            /// <param name="flags"></param>
            /// <param name="selfRelation">true if relation is a "self relationship"</param>
            protected Storage(string name, StorageFlags flags, bool selfRelation)
            {
                this.name = name;
                this.flags = flags;
                this.selfRelation = selfRelation;
            }

            /// <summary>
            /// Returns the name of the storage
            /// </summary>
            public string Name
            {
                get
                {
                    return name;
                }
                set
                {
                    name = value;
                }
            }

            /// <summary>
            /// Returns storage flags
            /// </summary>

            public StorageFlags Flags
            {
                get
                {
                    return flags;
                }
                set
                {
                    flags = value;
                }
            }

            /// <summary>
            /// Returns true if this is a N:N self relationship
            /// </summary>
            public bool IsSelfRelation
            {
                get
                {
                    return selfRelation;
                }
                set
                {
                    selfRelation = value;
                }
            }

            /// <summary>
            /// Returns the name of the class
            /// </summary>
            /// <returns></returns>
            public override string ToString() { return this.name; }

            /// <summary>
            /// Compares two storage types
            /// </summary>
            /// <param name="obj"></param>
            /// <returns></returns>
            public override bool Equals(object obj)
            {
                if (obj is Storage)
                {
                    Storage other = (Storage)obj;
                    return this.Name.Equals(other.Name, StringComparison.InvariantCultureIgnoreCase);
                }
                else
                {
                    return base.Equals(obj);
                }
            }

            /// <summary>
            /// Default implementation
            /// </summary>
            /// <returns></returns>
            public override int GetHashCode()
            {
                return base.GetHashCode();
            }
        }
    }
}
